package com.java.Servlet;

import com.google.gson.Gson;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Servlet帮助类
 */
public abstract class ServletUtil extends HttpServlet {
    // 设置编码方式乱码
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 注意顺序不要乱，否则相当于白设置编码
        req.setCharacterEncoding("utf-8");
        super.service(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    // 请求分发
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 从上下文中获取方法名 或 从请求参数op中获取方法名
        // String methodName = req.getPathInfo().substring(1);
        String methodName = req.getParameter("op");

        //激活当前方法
        boolean invoke = false;
        Method[] methods = this.getClass().getDeclaredMethods();
        for (Method m : methods) {
            if (m.getName().equals(methodName)) {
                try {
                    m.setAccessible(true);
                    m.invoke(this, req, resp);
                    invoke = true;
                } catch (ReflectiveOperationException e) {
                    e.printStackTrace();
                }
            }
        }
        if (!invoke) {
            response404(resp);
        }
    }

    protected void response404(HttpServletResponse resp) throws IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter printWriter = resp.getWriter();
        printWriter.println("404");
        printWriter.close();
    }

    // 将请求参数设置到Java对象中
    protected <T> T parseParamsToBean(Class<T> cls, HttpServletRequest req) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        // 解析参数
        Map<String, String[]> parameterMap = req.getParameterMap();

        // 获取Bean中的所有公共setXxx方法
        List<Method> setMethods = new ArrayList<>();
        for (Method m : cls.getMethods()) {
            if (m.getName().startsWith("set")) {
                setMethods.add(m);
            }
        }

        // 循环设置值
        T t = cls.newInstance();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            for (Method setMethod : setMethods) {
                String value = entry.getValue()[0];

                if (setMethod.getName().equalsIgnoreCase("set" + entry.getKey())) {
                    String typeName = setMethod.getParameterTypes()[0].getTypeName();
                    if ("int".equalsIgnoreCase(typeName) || "java.lang.Integer".equalsIgnoreCase(typeName)) {
                        setMethod.invoke(t, Integer.parseInt(value));
                    } else if ("long".equalsIgnoreCase(typeName) || "java.lang.Long".equalsIgnoreCase(typeName)) {
                        setMethod.invoke(t, Long.parseLong(value));
                    } else if ("float".equalsIgnoreCase(typeName) || "java.lang.Float".equalsIgnoreCase(typeName)) {
                        setMethod.invoke(t, Float.parseFloat(value));
                    } else if ("double".equalsIgnoreCase(typeName) || "java.lang.Double".equalsIgnoreCase(typeName)) {
                        setMethod.invoke(t, Double.parseDouble(value));
                    } else if ("boolean".equalsIgnoreCase(typeName) || "java.lang.Boolean".equalsIgnoreCase(typeName)) {
                        setMethod.invoke(t, Boolean.parseBoolean(value));
                    } else {
                        setMethod.invoke(t, value);
                    }
                    break;
                }
            }
        }

        return t;
    }

    // 将响应数据转为Json字符串响应
    protected void responseToJson(JsonModel jsonModel, HttpServletResponse resp) throws IOException {
        Gson gson = new Gson();
        String json = gson.toJson(jsonModel);

        resp.setContentType("application/json;charset=utf-8");
        PrintWriter printWriter = resp.getWriter();
        printWriter.println(json);
        printWriter.close();
    }

    class JsonModel {
        private Integer code; // 响应码
        private String msg; // 错误消息
        private Object data; // 响应体

        public Integer getCode() {
            return code;
        }

        public void setCode(Integer code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public Object getData() {
            return data;
        }

        public void setData(Object data) {
            this.data = data;
        }
    }
}
